package planner;

import java.io.CharArrayReader;
import java.util.Collection;

import fatworm.planner.QueryPlanner;
import fatworm.planner.UpdatePlanner;

import parser.absyn.*;
import parser.*;
import represent.Scan;
import represent.type.Type;
import represent.expression.Expression;
import represent.Plan;
import storage.transaction.Transaction;

/**
 * The object that executes SQL statements.
 * @author sciore
 */
public class Planner {
	private Yylex lexer;
	private Parser parser;
	private QueryPlanner qplanner;
	private UpdatePlanner uplanner;

	public Planner(QueryPlanner qplanner, UpdatePlanner uplanner) {
		this.qplanner = qplanner;
		this.uplanner = uplanner;
	}

	public UpdatePlanner updatePlanner() {
		return uplanner;
	}

	public QueryPlanner queryPlanner() {
		return qplanner;
	}

	public void execute(String sql, Transaction tx) {
		Object absyn = null;
		try {
			lexer = new Yylex(new CharArrayReader(sql.toCharArray()));
			parser = new Parser(lexer);
			absyn = parser.parse().value;
		} catch (Exception e) {
			System.err.println("Syntax Error.");
			e.printStackTrace();
			System.exit(-1);
		}
		if(absyn instanceof Query) {
			FetchData fetcher = new FetchData();
			QueryData data = fetcher.scanQuery((Query) absyn, tx);
			data.preprocess(tx);
			Plan p = data.execute(tx);
			Scan s = p.open(null);
			// TODO
			Collection<Expression> exprs = data.getSelectExp();
			System.out.println("Output begins");
			for(Expression e: exprs)
				System.out.print(e + "\t");
			System.out.println();
			while(s.next()) {
				for(Expression e: exprs) {
					Type c = e.evaluate(s);
					System.out.print(c.asJavaVal().toString() + "\t");
				}
				System.out.println();
			}
		}
		else if(absyn instanceof Manipulation) {
			FetchData fetcher = new FetchData();
			ManipulateData data = fetcher.scanMan((Manipulation) absyn, tx);
			data.execute(tx);
		}
		else throw new Error("Unknown Absyn.");
	}

}
